package perfumecabinet

import (
	"context"
	"strconv"
	"strings"

	"mall/common/globalkey"
	"mall/common/jwt"
	"mall/common/resultx"
	"mall/common/utils/pointy"
	"mall/service/blog/rpc/blogclient"
	"mall/service/forum/api/internal/svc"
	"mall/service/forum/api/internal/types"
	"mall/service/forum/api/internal/utils/parse"
	"mall/service/forum/rpc/forumclient"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetPerfumeCabinetListLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// 香水柜列表
func NewGetPerfumeCabinetListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetPerfumeCabinetListLogic {
	return &GetPerfumeCabinetListLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetPerfumeCabinetListLogic) GetPerfumeCabinetList(
	req *types.PerfumeCabinetListReq,
	headers *[]*types.Header,
) (*types.PerfumeCabinetListResp, error) {
	userId := jwt.GetUserId(l.ctx)
	if userId == 0 {
		return nil, resultx.NewErrCode(resultx.TOKEN_EXPIRE_ERROR)
	}

	if req.ObjectType == nil || *req.ObjectType == 0 {
		return nil, resultx.StatusError(resultx.FORUM_PERFUME_CABINET_OBJECT_TYPE_REQUIRED, "")
	}

	page, pageSize := parse.ParsePageInfo(
		req.Current,
		req.PageSize,
		l.svcCtx.Config.Query.DefaultAmount,
		l.svcCtx.Config.Query.MaxAmount,
	)

	filters := []string{"UserId,equalTo:" + strconv.FormatUint(userId, 10)}
	if req.ObjectType != nil {
		filters = append(filters, "ObjectType,equalTo:"+strconv.FormatInt(int64(*req.ObjectType), 10))
	}
	if req.Status != nil {
		filters = append(filters, "Status,equalTo:"+strconv.FormatInt(int64(*req.Status), 10))
	}
	preload := "forumPerfumeCabinet:Id,UserId,ObjectId,ObjectType,Status,UpdatedAt"
	eagerLoad := "forumPerfumeCabinet:total"
	res, err := l.svcCtx.ForumRpc.GetPerfumeCabinetList(l.ctx, &forumclient.BaseListReq{
		Offset:     uint32((page - 1) * pageSize),
		Limit:      uint32(pageSize),
		Preload:    pointy.GetPointer(preload),
		EagerLoad:  pointy.GetPointer(eagerLoad),
		Filter:     pointy.GetPointer(strings.Join(filters, ";")),
		VisitorId:  pointy.GetPointer(userId),
		PlatformId: pointy.GetPointer(globalkey.ThirdPartyPlatformWechatMini),
	})
	if err != nil {
		return nil, err
	}

	var hasNextPage bool
	var hasPreviousPage bool
	if res.HasNextPage != nil && *res.HasNextPage > 0 {
		hasNextPage = true
	}
	if res.HasPreviousPage != nil && *res.HasPreviousPage > 0 {
		hasPreviousPage = true
	}

	resp := &types.PerfumeCabinetListResp{
		BaseListInfo: types.BaseListInfo{
			Total:           res.Total,
			HasNextPage:     hasNextPage,
			HasPreviousPage: hasPreviousPage,
		},
	}

	if len(res.List) > 0 {
		var pids []string
		var perfumeMap map[uint64]*types.KbEntryInfo
		for _, v := range res.List {
			if v.ObjectId != nil && *v.ObjectId > 0 {
				pids = append(pids, strconv.FormatUint(*v.ObjectId, 10))
			}
		}
		if len(pids) > 0 {
			perfumeMap, err = l.getKBPostListByIds(pids)
			if err != nil {
				return nil, err
			}
		}

		for _, v := range res.List {
			var kbPost *types.KbEntryInfo
			if v.ObjectId != nil && *v.ObjectId > 0 && perfumeMap != nil {
				if pv, ok := perfumeMap[*v.ObjectId]; ok {
					kbPost = pv
				}
			}

			resp.List = append(resp.List, &types.PerfumeCabinetListInfo{
				Id:         v.Id,
				UserId:     v.UserId,
				ObjectId:   v.ObjectId,
				ObjectType: v.ObjectType,
				Status:     v.Status,
				CreatedAt:  v.CreatedAt,
				KBPost:     kbPost,
			})
		}
	}

	return resp, nil
}

func (l *GetPerfumeCabinetListLogic) getKBPostListByIds(ids []string) (map[uint64]*types.KbEntryInfo, error) {
	if len(ids) == 0 {
		return nil, nil
	}

	preload := "blogBook:Id,Title,Slug;blogBookMeta:mediaUrl;blogMedia:Uri,Url"
	eagerLoad := "blogBook:blogBookMeta,blogMedia"
	var filters []string
	filters = append(filters, "Status,equalTo:"+strconv.FormatInt(int64(globalkey.PostStatusPublish), 10))
	filters = append(filters, "Id,in:"+strings.Join(ids, ","))

	res, err := l.svcCtx.BlogRpc.GetKBPostListTmp(l.ctx, &blogclient.BaseListReq{
		Preload:   pointy.GetPointer(preload),
		EagerLoad: pointy.GetPointer(eagerLoad),
		Filter:    pointy.GetPointer(strings.Join(filters, ";")),
	})
	if err != nil {
		logx.Infow("GetPerfumeCabinetList getKBPostListByIds BlogRpc.GetKBPostListTmp err", logx.Field("detail", err.Error()))
		return nil, err
	}

	if len(res.List) > 0 {
		resp := make(map[uint64]*types.KbEntryInfo)
		for _, v := range res.List {
			if v.Id == nil || *v.Id == 0 {
				continue
			}

			var mediaUrl *string
			if len(v.Meta) > 0 {
				for _, m := range v.Meta {
					if m.Key == nil || m.Value == nil {
						continue
					}

					val := *m.Value
					switch *m.Key {
					case "mediaUrl":
						mediaUrl = pointy.GetPointer(val)
					}
				}
			}

			// var media []*types.TmpMediaInfo
			if mediaUrl == nil && len(v.Media) > 0 {
				for _, m := range v.Media {
					var url string
					if m.Url != nil && len(*m.Url) > 0 {
						url = *m.Url
					}
					if len(url) == 0 && m.Uri != nil && len(*m.Uri) > 0 {
						url = *m.Uri
					}
					if len(url) > 0 {
						mediaUrl = pointy.GetPointer(url)
					}

					// media = append(media, &types.TmpMediaInfo{
					// 	Uid:       m.Uid,
					// 	Id:        m.Id,
					// 	Thumbnail: m.Thumbnail,
					// 	Order:     m.Order,
					// 	Url:       pointy.GetPointer(url),
					// 	AltText:   m.AltText,
					// })
				}
			}

			resp[*v.Id] = &types.KbEntryInfo{
				Id:       v.Id,
				Title:    v.Title,
				Slug:     v.Slug,
				ImageUrl: mediaUrl,
			}
		}

		return resp, nil
	}

	return nil, nil
}
